#include "CSDLInputHandler.h"
#include <SDL.h>

CSDLInputHandler::CSDLInputHandler(CLivingObject *pPlayer, KeyMapping *keyMapping)
{
	if(pPlayer == NULL)
	{
		writeDebugOutput("The player pointer was NULL! Thats bad - aborting!");
	}

	if(SDL_WasInit(SDL_INIT_VIDEO) == 0) // Video inits also the event system
	{
		if(SDL_InitSubSystem(SDL_INIT_VIDEO) != 0)
		{
			writeDebugOutput("SDL_INIT_VIDEO failed to initialise! Thats bad - aborting!");
			//TODO: throw exception
		}
	}

	SDL_WM_GrabInput(SDL_GRAB_ON);
	SDL_ShowCursor(SDL_DISABLE);
	m_pPlayer = pPlayer;
	mapInputConfigToSDLEnum(keyMapping);
}

CSDLInputHandler::~CSDLInputHandler()
{
	if(SDL_WasInit(SDL_INIT_VIDEO) != 0)
	{
		SDL_QuitSubSystem(SDL_INIT_VIDEO);
	}
}

bool CSDLInputHandler::checkEvents()
{
	// This function is called every time a new frae is rendered, so it is ok do calc the fps here
	// But we should move the next if() to somewhere else when we have time (InputFrameListener shuld be SDL free..)
	m_lFrame++;
	if(m_TimerSecond.getMilliseconds() > 1000)
	{
		double dFPS = 0.0;
		char carrFPS[32];
		dFPS = (double)m_lFrame / ((double)m_TimerFPS.getMilliseconds() / 1000.0);

		sprintf_s(carrFPS,32,"%lf FPS",dFPS);

		SDL_WM_SetCaption(carrFPS, NULL);
		
		m_TimerSecond.reset(); // reset the timer so we can count to 1sec again
	}

	while(SDL_PollEvent(&m_evSDLEvent))
	{
		if(m_evSDLEvent.type == SDL_KEYDOWN)
		{
			processKeyDown(&m_evSDLEvent);
		}
		else if(m_evSDLEvent.type == SDL_KEYUP)
		{
			processKeyUp(&m_evSDLEvent);
		}
		else if(m_evSDLEvent.type == SDL_MOUSEBUTTONDOWN)
		{
			processMouseDown(&m_evSDLEvent);
		}
		else if(m_evSDLEvent.type == SDL_MOUSEBUTTONUP)
		{
			processMouseUp(&m_evSDLEvent);
		}
		else if(m_evSDLEvent.type == SDL_MOUSEMOTION)
		{
			processMouseMove(&m_evSDLEvent);
		}
	}
	return true;
}

void CSDLInputHandler::processKeyUp(SDL_Event *m_evSDLEvent)
{
	if(m_evSDLEvent->key.keysym.sym == m_keyTable.Right)
	{
		m_pPlayer->MoveX(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Left)
	{
		m_pPlayer->MoveX(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Up)
	{
		m_pPlayer->MoveY(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Down)
	{
		m_pPlayer->MoveY(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Backward)
	{
		m_pPlayer->MoveZ(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Forward)
	{
		m_pPlayer->MoveZ(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Menu)
	{
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Run)
	{
		m_pPlayer->setSprintMove(false);
	}
}
void CSDLInputHandler::processKeyDown(SDL_Event *m_evSDLEvent)
{
	if(m_evSDLEvent->key.keysym.sym == m_keyTable.Right)
	{
		m_pPlayer->MoveX(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Left)
	{
		m_pPlayer->MoveX(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Up)
	{
		m_pPlayer->MoveY(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Down)
	{
		m_pPlayer->MoveY(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Backward)
	{
		m_pPlayer->MoveZ(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Forward)
	{
		m_pPlayer->MoveZ(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Menu)
	{
		writeDebugOutput("COisBufferedInputHandler::keyPressed(): catching ESC");
		m_bContinue = false;
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Run)
	{
		m_pPlayer->setSprintMove(true);
	}
}
void CSDLInputHandler::processMouseUp(SDL_Event *m_evSDLEvent)
{
	;
}
void CSDLInputHandler::processMouseDown(SDL_Event *m_evSDLEvent)
{
	;
}
void CSDLInputHandler::processMouseMove(SDL_Event *m_evSDLEvent)
{
	m_pPlayer->Rotate( m_evSDLEvent->motion.xrel, m_evSDLEvent->motion.yrel, 0);
}

void CSDLInputHandler::mapInputConfigToSDLEnum(KeyMapping *keyMapping)
{
	// This is a default map - uncomment for debugging reasons only!
	m_keyTable.Forward = SDLK_w;
	m_keyTable.Backward = SDLK_s;
	m_keyTable.Up = SDLK_SPACE;
	m_keyTable.Down = SDLK_LCTRL;
	m_keyTable.Left = SDLK_a;
	m_keyTable.Right = SDLK_d;
	m_keyTable.Menu = SDLK_ESCAPE;
	m_keyTable.Run = SDLK_LSHIFT;

	// Map the keys
	m_keyTable.Forward = getSDLEnum(keyMapping->carrForward);
	m_keyTable.Backward = getSDLEnum(keyMapping->carrBackward);
	m_keyTable.Up = getSDLEnum(keyMapping->carrUp);
	m_keyTable.Down = getSDLEnum(keyMapping->carrDown);
	m_keyTable.Left = getSDLEnum(keyMapping->carrLeft);
	m_keyTable.Right = getSDLEnum(keyMapping->carrRight);
}

SDLKey CSDLInputHandler::getSDLEnum(char *carrKey)
{
	// if the first char is a lower chase letter, we have a single char that we can cast directly
	if( (int)carrKey[0] >= 97 && (int)carrKey[0] <= 122 )
	{
		return (SDLKey)((int)carrKey[0]);
	}
	else
	{
		if(strcmp(carrKey, "Shift") == 0)
		{
			return SDLK_LSHIFT;
		}
		else if(strcmp(carrKey, "Ctrl") == 0)
		{
			return SDLK_LCTRL;
		}
		else if(strcmp(carrKey, "ESC") == 0)
		{
			return SDLK_ESCAPE;
		}
		else if(strcmp(carrKey, "ALT") == 0)
		{
			return SDLK_LALT;
		}
		else if(strcmp(carrKey, "Tab") == 0)
		{
			return SDLK_TAB;
		}
		else if(strcmp(carrKey, "Return") == 0)
		{
			return SDLK_RETURN;
		}
		else if(strcmp(carrKey, "Up") == 0)
		{
			return SDLK_UP;
		}
		else if(strcmp(carrKey, "Down") == 0)
		{
			return SDLK_DOWN;
		}
		else if(strcmp(carrKey, "Left") == 0)
		{
			return SDLK_LEFT;
		}
		else if(strcmp(carrKey, "Right") == 0)
		{
			return SDLK_RIGHT;
		}
		else if(strcmp(carrKey, "Backspace") == 0)
		{
			return SDLK_BACKSPACE;
		}
		else if(strcmp(carrKey, "Space") == 0)
		{
			return SDLK_SPACE;
		}
	}
	return SDLK_UNKNOWN;
}